package com.itgaohe.service;



import com.alibaba.fastjson.JSONObject;
import com.itgaohe.common.context.UserContext;
import com.itgaohe.dao.entity.Chat;
import com.itgaohe.service.impl.ChatServiceImpl;
import com.itgaohe.utils.Result;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.concurrent.CopyOnWriteArraySet;


@Slf4j
@Component
@ServerEndpoint(value = "/chat/{userId}")
public class WebsocketServerEndpoint {

    private static ChatServiceImpl chatService;
    @Autowired
    public void setChatSessionService(ChatServiceImpl chatService) {
        WebsocketServerEndpoint.chatService = chatService;
    }

    //在线连接数
    private static long online = 0;

    //用于存放当前Websocket对象的Set集合
    private static CopyOnWriteArraySet<WebsocketServerEndpoint> websocketServerEndpoints = new CopyOnWriteArraySet<>();

    //与客户端的会话Session
    private Session session;

    //当前会话窗口ID
    private Long fromId = null ;

    /**
     * 链接成功调用的方法
     *
     * @param session
     * @param userId
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") Long userId) {
        log.info("onOpen >> 链接成功");
        this.session = session;
        //将当前websocket对象存入到Set集合中
        websocketServerEndpoints.add(this);
        //在线人数+1
        addOnlineCount();
        this.fromId = userId;
        log.info("有新窗口开始监听：" + userId + ", 当前在线人数为：" + getOnlineCount());
    }

    /**
     * 链接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        log.info("onClose >> 链接关闭");

        //移除当前Websocket对象
        websocketServerEndpoints.remove(this);

        //在内线人数-1
        subOnLineCount();

        log.info("链接关闭，当前在线人数：" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     */
    @OnMessage
    public void onMessage(String message) throws IOException {
        log.info("接收到窗口：" + fromId + " 的信息：" + message);


    }

    @OnError
    public void onError(Throwable e) {
        e.printStackTrace();
    }

    /**
     * 推送消息
     *
     * @param message
     */
    private void sendMessage(String message) throws IOException {
        log.info("发送消息至好友" + session.toString() + "   " + message);
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 封装返回消息
     *
     */
    private String getData(Chat chat) {
        return JSONObject.toJSONString(Result.ok(chat));
    }

    /**
     * 指定窗口推送消息
     *
     */
    public void sendTo(Chat chat) {
        Long formId = UserContext.getUser().getId() ;
        chat.setTimestamp(LocalDateTime.now());
        chat.setFromId(formId);
        for (WebsocketServerEndpoint endpoint : websocketServerEndpoints) {
            try {
                if (endpoint.fromId == chat.getToId()) {
                    log.info(chat.getFromId() + " 推送消息到窗口：" + chat.getToId() + " ，推送内容：" + chat.getContent());
                    endpoint.sendMessage(getData(chat));
                }
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
        new Thread(() -> {
            chatService.sendMessage(chat) ;
        }).start();

    }

    private void subOnLineCount() {
        WebsocketServerEndpoint.online--;
    }

    private synchronized long getOnlineCount() {
        return online;
    }

    private void addOnlineCount() {
        WebsocketServerEndpoint.online++;
    }
}
